package com.ssy.lingxi.member.merchant.serviceimpl.mobile;

import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.MemberRightTypeEnum;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.MemberRightHistoryDO;
import com.ssy.lingxi.member.merchant.entity.MemberRightSpendHistoryDO;
import com.ssy.lingxi.member.merchant.model.constant.MemberRightScoreBehaviorEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberValidateStatusEnum;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberRightScoreVO;
import com.ssy.lingxi.member.merchant.model.vo.manage.request.MemberAndRoleIdVO;
import com.ssy.lingxi.member.merchant.model.vo.mobile.request.MobileRightScoreHistoryPageVO;
import com.ssy.lingxi.member.merchant.model.vo.mobile.request.MobileShopRightScorePageVO;
import com.ssy.lingxi.member.merchant.model.vo.mobile.response.MobileRightScoreHistoryVO;
import com.ssy.lingxi.member.merchant.model.vo.mobile.response.MobileRightScoreVO;
import com.ssy.lingxi.member.merchant.model.vo.mobile.response.MobileShopRightScoreHistoryVO;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRightHistoryRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRightSpendHistoryRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberLevelConfigService;
import com.ssy.lingxi.member.merchant.service.mobile.IMobileLrcService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * App - 会员等级、权益、信用相关接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2020-12-17
 */
@Service
public class MobileLrcServiceImpl implements IMobileLrcService {
    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private MemberRightHistoryRepository memberRightHistoryRepository;

    @Resource
    private MemberRightSpendHistoryRepository memberRightSpendHistoryRepository;

    @Resource
    private IBaseMemberLevelConfigService baseMemberLevelConfigService;

    @Resource
    private JdbcTemplate jdbcTemplate;

    /**
     * “积分订单” - 查询平台通用和会员专有权益积分
     *
     * @param headers Http头部信息
     * @param idVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberRightScoreVO> getMemberRightScore(HttpHeaders headers, MemberAndRoleIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromMobile(headers);
        return baseMemberLevelConfigService.getMemberRightPoint(idVO.getMemberId(), idVO.getRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId());
    }

    /**
     * “我的积分” - 分页查询列表
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MobileRightScoreVO>> pageRightScore(HttpHeaders headers, PageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromMobile(headers);

        Pageable page = PageRequest.of(pageVO.getCurrent() -1, pageVO.getPageSize(), Sort.by("id").ascending());
        Specification<MemberRelationDO> specification = (Specification<MemberRelationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), loginUser.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("verified").as(Integer.class), MemberValidateStatusEnum.VERIFY_PASSED.getCode()));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), MemberStatusEnum.NORMAL.getCode()));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberRelationDO> pageList = relationRepository.findAll(specification, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(relationDO -> {
            MobileRightScoreVO scoreVO = new MobileRightScoreVO();
            scoreVO.setValidateId(relationDO.getId());
            scoreVO.setMemberId(relationDO.getMemberId());
            scoreVO.setMemberName(relationDO.getMember().getName());
            scoreVO.setScore(relationDO.getLevelRight() == null ? 0 : relationDO.getLevelRight().getCurrentPoint());
            return scoreVO;
        }).collect(Collectors.toList())));
    }

    /**
     * “我的积分” - 分页查询权益积分历史记录
     *
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MobileRightScoreHistoryVO>> pageRightScoreHistory(HttpHeaders headers, MobileRightScoreHistoryPageVO pageVO) {
        memberCacheService.needLoginFromMobile(headers);

        MemberRelationDO relationDO = relationRepository.findById(pageVO.getValidateId()).orElse(null);
        if(relationDO == null || !relationDO.getMemberId().equals(pageVO.getMemberId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        switch (pageVO.getScope()) {
            case 1:
                return pageAllRightScoreHistory(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
            case 2:
                return pageRightScoreHistory(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
            case 3:
                return pageRightScoreSpendHistory(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
            default:
                return Wrapper.fail(ResponseCode.REQUEST_PARAM_CHECK_FAILED);
        }
    }

    /**
     * “找店铺 - 积分兑换” - 分页查询权益积分历史记录
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MobileShopRightScoreHistoryVO> pageShopRightScoreHistory(HttpHeaders headers, MobileShopRightScorePageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromMobile(headers);

        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(pageVO.getUpperMemberId(), pageVO.getUpperRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId());
        if(relationDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        Integer currentPoint = relationDO.getLevelRight().getCurrentPoint();

        Long totalCount;
        List<MobileRightScoreHistoryVO> dataList;

        if(pageVO.getType().equals(MemberRightScoreBehaviorEnum.Gain.getCode())) {
            Pageable pageable = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());
            Page<MemberRightHistoryDO> pageList = memberRightHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleIdAndRightTypeEnum(pageVO.getUpperMemberId(), pageVO.getUpperRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId(), MemberRightTypeEnum.SCORE_POINTS_RIGHT.getCode(), pageable);
            totalCount = pageList.getTotalElements();
            dataList = pageList.getContent().stream().map(memberRightHistoryDO -> {
                MobileRightScoreHistoryVO historyVO = new MobileRightScoreHistoryVO();
                historyVO.setOperation("成交订单");
                historyVO.setScore(memberRightHistoryDO.getPoint().intValue());
                historyVO.setDate(memberRightHistoryDO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                return historyVO;
            }).collect(Collectors.toList());

        } else if(pageVO.getType().equals(MemberRightScoreBehaviorEnum.Spend.getCode())) {
            Pageable pageable = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());
            Page<MemberRightSpendHistoryDO> pageList = memberRightSpendHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(pageVO.getUpperMemberId(), pageVO.getUpperRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId(), pageable);
            totalCount = pageList.getTotalElements();
            dataList = pageList.getContent().stream().map(memberRightSpendHistoryDO -> {
                MobileRightScoreHistoryVO historyVO = new MobileRightScoreHistoryVO();
                historyVO.setOperation(memberRightSpendHistoryDO.getSpendTypeName());
                historyVO.setScore(memberRightSpendHistoryDO.getPoint());
                historyVO.setDate(memberRightSpendHistoryDO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                return historyVO;
            }).collect(Collectors.toList());
        } else {
            Wrapper<PageData<MobileRightScoreHistoryVO>> result =  pageAllRightScoreHistory(pageVO.getUpperMemberId(), pageVO.getUpperRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
            if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(result.getCode(), result.getMessage());
            }

            totalCount = result.getData().getTotalCount();
            dataList = result.getData().getData();
        }


        MobileShopRightScoreHistoryVO historyVO = new MobileShopRightScoreHistoryVO();
        historyVO.setCurrentPoint(currentPoint);
        historyVO.setTotalCount(totalCount);
        historyVO.setData(dataList);

        return Wrapper.success(historyVO);
    }

    /**
     * 分页查询权益积分历史记录（包括获得的权益积分、消费的权益积分）
     * @param upperMemberId 上级会员Id
     * @param upperRoleId 上级会员角色Id
     * @param subMemberId 下级会员Id
     * @param subRoleId 下级会员角色Id
     * @param current 当前页
     * @param pageSize 每页行数
     * @return 查询结果
     */
    private Wrapper<PageData<MobileRightScoreHistoryVO>> pageAllRightScoreHistory(Long upperMemberId, Long upperRoleId, Long subMemberId, Long subRoleId, int current, int pageSize) {
        String countSql = "select count(*) from (\n" +
                "select '成交订单' as operation, to_char(create_time, 'YYYY-MM-DD HH24:MI:SS') as date, point as score from ms_mc_member_right_history\n" +
                "where right_type_enum = 3 and member_id = " + upperMemberId  + " and role_id = " + upperRoleId +" and sub_member_id = " + subMemberId + " and sub_role_id = " + subRoleId + " \n" +
                "union\n" +
                "select spend_type_name as operation, to_char(create_time, 'YYYY-MM-DD HH24:MI:SS') as date, -point as score from ms_mc_member_right_spend_history\n" +
                "where member_id = " + upperMemberId  + " and role_id = " + upperRoleId +" and sub_member_id = " + subMemberId + " and sub_role_id = " + subRoleId + " \n" +
                ") a";

        String pageSql = "select a.operation, left(a.date,10) as date, a.score from (\n" +
                "select '成交订单' as operation, to_char(create_time, 'YYYY-MM-DD HH24:MI:SS') as date, point as score from ms_mc_member_right_history\n" +
                "where right_type_enum = 3 and member_id = " + upperMemberId  + " and role_id = " + upperRoleId +" and sub_member_id = " + subMemberId + " and sub_role_id = " + subRoleId + " \n" +
                "union\n" +
                "select spend_type_name as operation, to_char(create_time, 'YYYY-MM-DD HH24:MI:SS') as date, -point as score from ms_mc_member_right_spend_history\n" +
                "where member_id = " + upperMemberId  + " and role_id = " + upperRoleId +" and sub_member_id = " + subMemberId + " and sub_role_id = " + subRoleId + " \n" +
                ") a \n" +
                "order by a.date desc \n" +
                "limit " + pageSize + " offset " + (current - 1) * pageSize;

        Long totalCount = jdbcTemplate.queryForObject(countSql, Long.class);
        if(totalCount == null) {
            totalCount = 0L;
        }

        List<MobileRightScoreHistoryVO> resultList = new ArrayList<>();
        if(totalCount > 0) {
            resultList = jdbcTemplate.query(pageSql, new BeanPropertyRowMapper<>(MobileRightScoreHistoryVO.class));
        }

        return Wrapper.success(new PageData<>(totalCount, resultList));
    }

    /**
     * 分页查询权益积分获取历史记录
     * @param upperMemberId 上级会员Id
     * @param upperRoleId 上级会员角色Id
     * @param subMemberId 下级会员Id
     * @param subRoleId 下级会员角色Id
     * @param current 当前页
     * @param pageSize 每页行数
     * @return 查询结果
     */
    private Wrapper<PageData<MobileRightScoreHistoryVO>> pageRightScoreHistory(Long upperMemberId, Long upperRoleId, Long subMemberId, Long subRoleId, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current - 1, pageSize, Sort.by("createTime").descending());
        Page<MemberRightHistoryDO> pageList = memberRightHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleIdAndRightTypeEnum(upperMemberId, upperRoleId, subMemberId, subRoleId, MemberRightTypeEnum.SCORE_POINTS_RIGHT.getCode(), pageable);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(history -> {
            MobileRightScoreHistoryVO historyVO = new MobileRightScoreHistoryVO();
            historyVO.setDate(history.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            historyVO.setOperation("成交订单");
            historyVO.setScore(history.getPoint().intValue());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 分页查询权益积分消费历史记录
     * @param upperMemberId 上级会员Id
     * @param upperRoleId 上级会员角色Id
     * @param subMemberId 下级会员Id
     * @param subRoleId 下级会员角色Id
     * @param current 当前页
     * @param pageSize 每页行数
     * @return 查询结果
     */
    private Wrapper<PageData<MobileRightScoreHistoryVO>> pageRightScoreSpendHistory(Long upperMemberId, Long upperRoleId, Long subMemberId, Long subRoleId, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current - 1, pageSize, Sort.by("createTime").descending());
        Page<MemberRightSpendHistoryDO> pageList = memberRightSpendHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(upperMemberId, upperRoleId, subMemberId, subRoleId, pageable);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(history -> {
            MobileRightScoreHistoryVO historyVO = new MobileRightScoreHistoryVO();
            historyVO.setDate(history.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            historyVO.setOperation(history.getSpendTypeName());
            historyVO.setScore(history.getPoint());
            return historyVO;
        }).collect(Collectors.toList())));
    }
}
